#ifndef __LOG_H__
#define __LOG_H__

#include <string>
#include <algorithm>
#include <sstream>
#include <memory>
#include <map>

#include "singleton.h"

#define LOG_LEVEL(logger, level) \
    LogEventWrap(LogEvent::ptr(new LogEvent(logger, __FILE__, __LINE__, time(0), level))).GetSS()

//debug日志
#define LOG_DEBUG(logger) LOG_LEVEL(logger, LogLevel::Level::DEBUG)

#define LOG_INFO(logger) LOG_LEVEL(logger, LogLevel::Level::INFO)

#define LOG_WARN(logger) LOG_LEVEL(logger, LogLevel::Level::WARN)

#define LOG_ERROR(logger) LOG_LEVEL(logger, LogLevel::Level::ERROR)

#define LOG_FATAL(logger) LOG_LEVEL(logger, LogLevel::Level::FATAL)

class Logger;

//日志级别
class LogLevel
{
public:
    enum Level
    {
        UNKNOW = 0,
        DEBUG = 1,
        INFO = 2,
        WARN = 3,
        ERROR = 4,
        FATAL = 5,
    };

    static const std::string ToString(LogLevel::Level level)
    {
    #define XX(level) \
        case LogLevel::level: \
        return #level;
        
        switch (level)
        {
            XX(UNKNOW);
            XX(DEBUG);
            XX(INFO);
            XX(WARN);
            XX(ERROR);
            XX(FATAL);
            default:
                return "UNKNOW";
        }
    #undef XX
    }

    static LogLevel::Level ToLevel(const std::string& str)
    {
    #define XX(level, s) \
        if(tmp == #s) \
            return LogLevel::level;
        
        std::string tmp = str;
        std::transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);

        XX(UNKNOW, UNKNOW);
        XX(DEBUG, DEBUG);
        XX(INFO, INFO);
        XX(WARN, WARN);
        XX(ERROR, ERROR);
        XX(FATAL, FATAL);

        return LogLevel::UNKNOW;
    #undef XX
    }

};

//日志事件类　存储所有的日志项
class LogEvent:public std::enable_shared_from_this<LogEvent>
{
public:
    typedef std::shared_ptr<LogEvent> ptr;
    LogEvent(std::shared_ptr<Logger> logger, const char* m_file, int32_t line, uint64_t time, LogLevel::Level level);

    ~LogEvent();

    std::stringstream& GetSS();

    std::shared_ptr<Logger> GetLogger();

    LogLevel::Level GetLevel() { return m_level; }

    void TimeOutPut(std::ostream& os);

    void LineOutPut(std::ostream& os);

    void LevelOutPut(std::ostream& os);

    void FileOutPut(std::ostream& os);

    void ContentOutPut(std::ostream& os);
private:
    //文件名
    const char* m_file;
    //行号
    uint32_t m_line;
    //时间戳
    time_t m_time;
    //日志级别
    LogLevel::Level m_level;
    //日志内容流
    std::stringstream m_ss;
    //日志器
    std::shared_ptr<Logger> m_logger;
};

//日志事件的包装类，用于析构是打印日志
class LogEventWrap
{
public:
    LogEventWrap(LogEvent::ptr e);

    ~LogEventWrap();

    std::stringstream& GetSS() { return m_event->GetSS(); } 

private:
    LogEvent::ptr m_event;
};

//日志器　打印日志
class Logger
{
public:
    typedef std::shared_ptr<Logger> ptr;

    Logger(const std::string& name);

    void Log(LogLevel::Level level, LogEvent::ptr event);


private:
    std::string m_name;
};

//日志器的管理类　
class LoggerManager
{
public:
    Logger::ptr GetLogger(const std::string& name);

private:
    std::map<std::string, Logger::ptr> m_loggers;
};

typedef Singleton<LoggerManager> LoggerMgr;

#endif // !__LOG_H__